﻿#include "ssSnowflake.h"
#include <cmath>

namespace StarSeeker
{

static const std::string BASE36_CHAR("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");

ssSnowflake::ssSnowflake()
{
	m_timeStamp = 0;
	m_inc = 0;
	m_serverID = 0;
	m_timeStampBegin = SS_SNOW_BEGIN_TIMESTAMP;
}

ssSnowflake::ssSnowflake(unsigned short serverID, int timeStampBegin)
{

	m_timeStamp = 0;
	m_inc = 0;
	m_serverID = serverID;
	m_timeStampBegin = timeStampBegin;
}

ssSnowflake::~ssSnowflake()
{
}

void ssSnowflake::Init(unsigned short serverID, int timeStampBegin)
{
	m_serverID = serverID;
	m_timeStamp = timeStampBegin;
}

long long ssSnowflake::GetID()
{
	long long id=0;
	do
	{
		time_t st = ::time(0) - m_timeStampBegin;
		if (st != m_timeStamp)
		{
			m_inc = 0;
			m_timeStamp = st;
		}
		id = m_timeStamp;
		id <<= 32;
		id |= (m_serverID << 18) | m_inc;
		m_inc++;
	} while (m_inc>SS_SNOW_MAX);
	return id;
}

unsigned int ssSnowflake::ParseTimeStamp(long long id)
{
	return (unsigned int)(id >> 32);
}

unsigned short ssSnowflake::ParseServerId(long long id)
{
	unsigned int id0 = (unsigned int)(id & 0x00000000ffffffff);
	return (unsigned short)(id0 >>18);
}

unsigned int ssSnowflake::ParseServerInc(long long id)
{
	unsigned long long id2 = id;
	return (unsigned int)(id2 << 46 >> 46);
}

std::string ssSnowflake::Adecimal10ToAdecimal36(long long num)
{
	std::string str;
	while (num > 0)
	{
		size_t cur = num % BASE36_CHAR.size();
		str = BASE36_CHAR[cur] + str;
		num = num / BASE36_CHAR.size();
	}
	return str;
}

long long ssSnowflake::Adecimal36ToAdecimal10(std::string& strNo)
{
	long long num = 0;
	for (size_t i = 0; i < strNo.size(); i++)
	{
		num += BASE36_CHAR.find(strNo[i]) * ::pow(BASE36_CHAR.size(), strNo.size() - i - 1);
	}
	return num;
}

long long ssSafeSnowflake::GetSafeID()
{
	long long ret = 0;
	m_lock.Lock();
	ret = GetID();
	m_lock.Unlock();
	return ret;
}

ssSnowflakeWT::ssSnowflakeWT()
{
	m_inc = 1;
	m_serverID = 0;
}

ssSnowflakeWT::ssSnowflakeWT(unsigned short serverID)
{
	m_inc = 1;
	m_serverID = serverID;
}

ssSnowflakeWT::~ssSnowflakeWT()
{
}

void ssSnowflakeWT::Init(unsigned short serverID)
{
	m_serverID = serverID;
}

long long ssSnowflakeWT::GetID()
{
	long long id = (m_serverID << 50) | m_inc;
	++m_inc;
	if (m_inc > SS_SNOWWT_MAX)
		m_inc = 1;

	return id;
}

unsigned short ssSnowflakeWT::ParseServerId(long long id)
{
	return (unsigned short)(id >> 50);
}

long long ssSnowflakeWT::ParseServerInc(long long id)
{
	return id << 14 >> 14;
}

long long ssSafeSnowflakeWT::GetSafeID()
{
	long long ret = 0;
	m_lock.Lock();
	ret = GetID();
	m_lock.Unlock();
	return ret;
}

}
